#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#include <jack/jack.h>

const double PI = 3.1459;

jack_port_t *output_port;
jack_client_t *client;

typedef jack_default_audio_sample_t sample_t;

int _sample_size;
jack_nframes_t sr;
sample_t* cycle;
jack_nframes_t samincy;
long offset=0;

int tone=5;

int process(jack_nframes_t nframes, void *arg) {

  jack_default_audio_sample_t *out = (jack_default_audio_sample_t *) jack_port_get_buffer(output_port, nframes);

  jack_nframes_t i;
  for(i=0;i < nframes;i++){
    out[i]=cycle[offset];
    offset++;
    if(offset==samincy)
      offset=0;    
  }
  return 0;
}

int srate(jack_nframes_t nframes, void *arg) {
  //fprintf(stderr, "sample rate %lu/sec.\n", nframes);
}

void jack_shutdown(void *arg) {
  fprintf(stderr, "Jack shutdown, exiting.\n");
  exit(1);
}

int jackclient_init(float volume) {
  
  const char **ports;
  
  if((client = jack_client_open("Jack Silence", JackNullOption|JackNoStartServer, NULL)) == 0) {
    fprintf(stderr, "jack server not running?\n");
    exit(1); 
  }

  jack_set_process_callback(client, process, 0);
  jack_set_sample_rate_callback(client, srate, 0);
  jack_on_shutdown(client, jack_shutdown, 0);

  sr=jack_get_sample_rate (client);

  samincy=(sr/tone);
  sample_t scale = 2 * PI / samincy;
  cycle = (sample_t *) malloc (samincy * sizeof(sample_t));
  if(cycle == NULL) {
    fprintf(stderr,"memory allocation failed\n");
    return 1;
  }

  int i;
  for(i=0;i < samincy;i++){
    cycle[i]=sin((float)i*scale)*volume;
  }

  output_port = jack_port_register(client, "output", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);

  if(jack_activate(client)) {
    fprintf(stderr, "cannot activate client");
    exit(1);
  }
	
  if((ports = jack_get_ports(client, NULL, NULL, JackPortIsPhysical|JackPortIsInput)) == NULL) {
    fprintf(stderr, "Cannot find any physical playback ports\n");
    exit(1);
  }

  /*
  // connect to left channel
  if(jack_connect(client, jack_port_name(output_port), ports[8])) {
    fprintf(stderr, "cannot connect to output port\n");
  }

  // connect to right channel
  if(jack_connect(client, jack_port_name(output_port), ports[9])) {
    fprintf(stderr, "cannot connect to output port\n");
  }
  */

  free(ports);

  return 0;
}

void jackclient_close() {
  jack_client_close(client);
}

